using FakeItEasy;
using NUnit.Framework;

namespace Spring.Threading;

[TestFixture]
public class SyncHolderTest
{
    ISync sync;

    [SetUp]
    public void SetUp()
    {
        sync = A.Fake<ISync>();
    }

    [TearDown]
    public void TearDown()
    {
    }

    class MySemaphore : Semaphore
    {
        public MySemaphore(long initialPermits) : base(initialPermits)
        {
        }
    }

    [Test]
    public void CanBeUsedWithTheUsingCSharpIdiomToAttemptOnAnISync()
    {
        MySemaphore sync = new MySemaphore(1);
        using (new SyncHolder(sync, 100))
        {
            Assert.AreEqual(0, sync.Permits);
        }

        Assert.AreEqual(1, sync.Permits);

        sync = new MySemaphore(0);
        try
        {
            using (new SyncHolder(sync, 100))
            {
                Assert.IsTrue(false, "wrongly entered sync block");
            }
        }
        catch (TimeoutException)
        {
            Assert.AreEqual(0, sync.Permits);
        }
    }

    [Test]
    public void CanBeUsedWithTheUsingCSharpIdiomToAcquireAnIsync()
    {
        sync.Acquire();
        sync.Release();

        Assert.Throws<ThreadStateException>(() =>
        {
            using (new SyncHolder(sync))
            {
                throw new ThreadStateException();
            }
        });
    }
}
